<template>
  <div>
    <div class="content-box" :class="{ active: activeContent === 'formula' }">
      <div class="formula-tips">
        <a-tooltip
          placement="top"
          :overlay-style="{ userSelect: 'text' }"
          :mouse-leave-delay="0.5"
        >
          <template slot="title">
            <span>键入$选择需要处理的数据列</span><br />
            <a
              href="/docs/#/formula_guide?id=公式功能函数使用指南"
              target="_blank"
              style="color: #989fff; cursor: pointer; pointer-events: all;"
              >详见函数说明文档</a
            >
          </template>
          <span @mouseover="annotationHover()" @mouseout="annotationOut()">
            <a-icon-font
              v-show="isAnnotationHover"
              type="iconinfo-cirlce-obeifen"
            />
            <a-icon-font v-show="!isAnnotationHover" type="iconinfo-cirlce-o" />
          </span>
        </a-tooltip>
      </div>
      <div class="label">公式</div>
      <div class="expand">
        <formula-box
          :formula-err="formulaErr"
          :formula-value="formulaValue"
          :column-list="tableColumnList()"
          @cm:focus="handleFocus"
          @update:value="updateValue"
        >
        </formula-box>
        <!-- <code-mirror-editor
          class="input-style"
          :class="{ error_border: formulaErr.length > 0 }"
          :value="formulaValue"
          mode="javascript"
          height="80"
          from="formula"
          :table-list="tableColumnList()"
          @cm:focus="handleFocus('formula')"
          @update:value="updateValue"
        ></code-mirror-editor>
        <p v-if="formulaErr.length > 0" class="warning-text">
          {{ formulaErr }}
        </p> -->
      </div>
    </div>
    <div
      class="content-box"
      :class="{ active: activeContent === 'columnName' }"
    >
      <div class="label">新列名</div>
      <div class="expand">
        <a-input
          v-model="newColumnName"
          class="input-style column-input"
          :class="{ error_border: columnNameErr.length > 0 }"
          @focus="handleFocus('columnName')"
          @change="columnNameErr = ''"
        ></a-input>
        <p v-if="columnNameErr.length > 0" class="warning-text">
          {{ columnNameErr }}
        </p>
      </div>
    </div>
  </div>
</template>

<script lang="ts">
import { Component, Prop, Watch, Vue } from 'vue-property-decorator'
import DataStore from '@/store/modules/dataview'
import FormulaBox from './formulaBox.vue'

@Component({
  components: {
    FormulaBox,
  },
})
export default class FormulaForm extends Vue {
  @Prop({
    type: String,
    default() {
      return ''
    },
  })
  formulaValue: String | undefined

  @Prop({
    type: String,
    default() {
      return ''
    },
  })
  columnName?: String

  @Prop({
    type: String,
    default() {
      return ''
    },
  })
  baseCol?: String

  @Watch('formulaValue', {
    immediate: true,
  })
  handleFormulaVal(newValue: string) {
    this.formulaBody = newValue
  }

  @Watch('columnName', {
    immediate: true,
  })
  handleColName(newValue: string) {
    this.newColumnName = newValue
  }
  private formulaErr: string = ''
  private columnNameErr: string = ''
  public formulaBody: string = '' //  传递给后端的值
  public newColumnName: string = ''
  private activeContent: string = ''
  private isAnnotationHover = false
  public annotationHover() {
    this.isAnnotationHover = true
  }
  public annotationOut() {
    this.isAnnotationHover = false
  }

  private get formulaColName() {
    return DataStore.formulaColName
  }

  private get tableName(): string {
    // 查询数据的表名取决于当前历史记录的表名，没有的话取selectnode的表名
    if (DataStore.autojoinTableName) {
      // autojoin 预览表数据
      return DataStore.autojoinTableName
    }
    return this.selectNodeTableInfo?.tableName
  }

  public get selectNodeTableInfo() {
    // 节点id和表名组成的唯一信息
    return DataStore.selectNodeTableInfo || { nodeId: '', tableName: '' }
  }

  public tableColumnList(): any {
    //  键入$ 后，hint 显示完整： c1 - 数字列； c2 - 日期列； 选择之后$c1
    //  when edit history - 去除当前列
    let index = 1
    const result: Array<string> = []
    this.tableColumns.forEach((x: any) => {
      if (x.name !== this.formulaColName) {
        result.push(`c${index} - ${x.name}`)
        index += 1
      }
    })
    return result
  }

  /** selected 列信息 */
  //  多列返回多个数组
  public get tableSelectColumns() {
    return DataStore.tableSelectColumns
  }

  /** 所有列信息 */
  public get tableColumns() {
    return DataStore.tableColumns
  }

  private get currentHistory() {
    return DataStore.currentHistory
  }

  //  更新cell代码的值
  public updateValue(value: string) {
    this.formulaBody = value
    this.formulaErr = ''
  }

  public handleFocus(name: string) {
    this.activeContent = name
  }
  //  init or close panel
  public clearText() {
    this.formulaErr = ''
    this.columnNameErr = ''
    this.formulaBody = ''
    this.newColumnName = ''
  }
  //  点击取消 btn - 清空，关闭推荐面板
  public cancel() {
    this.clearText()
  }
  //  检测列名是否为空
  public checkNameIfEmpty() {
    if (this.newColumnName.trim().length === 0) {
      this.columnNameErr = '列名不能为空，请重新输入'
      return false
    }
    return true
  }

  //  列名是否一致【需要去除列名空白符的比较】
  public checkNameRepeat() {
    // @ts-ignore
    for (let i = 0, { length } = this.tableColumns; i < length; i += 1) {
      if (this.tableColumns[i].name === this.newColumnName.trim()) {
        //  编辑操作历史的时候，允许用户列名 和 历史列名重复！！！！
        if (
          this.columnName &&
          this.columnName.trim() === this.newColumnName.trim()
        ) {
          // eslint-disable-next-line no-continue
          continue
        }
        this.columnNameErr = '列名已存在，请重新输入'
        return false
      }
    }
    return true
  }
  //  检测公式value 长度是否超过上限1024 且 不能为 空
  public checkFormulaLength() {
    if (this.formulaBody.length > 1024) {
      this.formulaErr = '公式长度超过1024，请重新输入'
      return false
    }
    if (this.formulaBody.trim().length === 0) {
      this.formulaErr = '公式不能为空，请输入有效公式'
      return false
    }
    return true
  }
  //  公式内不支持大括号，双引号
  public checkFormulaForbidCharacter() {
    if (this.formulaBody.includes('"')) {
      this.formulaErr = '请使用单引号代替双引号'
      return false
    }
    if (/[[\]]/.test(this.formulaBody)) {
      this.formulaErr = '请勿使用大括号'
      return false
    }
    return true
  }

  //  确认按钮之后的操作： 1. 列名重复检测 2. 公式长度1024上限检测 3. js lint error 检测，有的话无法提交  4. 校验api 5. addAction
  public async doOption() {
    if (
      this.checkFormulaLength() &&
      this.checkNameIfEmpty() &&
      this.checkNameRepeat() &&
      this.checkFormulaForbidCharacter()
    ) {
      //  先call 校验api， 再 addAction
      const data = {
        action: 'ADD_COLUMN_BASED_ON_FORMULA',
        actionType: 'formulaColumn',
        formula: this.formulaBody,
        description: this.formulaBody, //  截取公式前10个字符
        col: this.baseCol ? this.baseCol : this.tableSelectColumns[0].name, //  add - 根据所选列； update - 根据history 里的col
        newColumn: this.newColumnName,
        id: this.currentHistory ? this.currentHistory.data.id : '', // 父记录id或者当前编辑的记录id
        table: this.tableName,
        isEdit: !!this.columnName,
      }
      const request = DataStore.checkFormula
      const { result } = await request({
        data,
      })

      if (result.status === 'FAIL') {
        this.formulaErr = JSON.parse(result.logInfo).error_msg
      } else {
        //  post api
        this.$emit('actiondone', data)
        DataStore.setShowColumnIndex(false)
      }
    }
  }
}
</script>

<style lang="less" scoped>
.content-box {
  align-items: baseline;
  display: flex;
  padding: 10px 28px 10px 19px;

  &:hover {
    background: rgba(103, 113, 252, 0.1);
  }
}

.content-box.active {
  background: rgba(103, 113, 252, 0.1);
}

.formula-tips {
  cursor: pointer;
}

.label {
  margin: 0 8px;
}

.expand {
  flex-grow: 1;
  max-width: 83%;
}

.input-style {
  border: 1px solid #cbceff;
  border-radius: 2px;
}

.input-style.error_border {
  border: 1px solid #e6505a;
}

.warning-text {
  color: #e6505a;
  display: inline-block;
  margin: 0;
  word-break: break-word;
}

.column-input {
  color: #373b52;
  font-family: monospace;
}
</style>
